<template>
  <div style="width:100%;overflow:hidden">
    <video id="monitor" autoplay style="width:100%">
    </video>
  </div>
</template>

<script>
  import RecordRTC from 'recordrtc'
  import global from '../lib/global'
  import blobToUrl from '../lib/blobToUrl'
  import axios from 'axios'

  // global variables
  var currentBrowser = !!navigator.mozGetUserMedia ? 'gecko' : 'chromium'

  // Firefox can record both audio/video in single webm container
  // Don't need to create multiple instances of the RecordRTC for Firefox
  var isRecordOnlyAudio = !!navigator.mozGetUserMedia//true

  var fileName,
    audioRecorder,
    videoRecorder,
    mediaStream = null,
    videoElement,
    worker,
    workerPath = global.server + '/ffmpeg-all-codecs.js',
    isFirefox = !!navigator.mozGetUserMedia,
    videoFile = !!navigator.mozGetUserMedia ? 'video.gif' : 'video.webm'

  export default {
    data() {
      return {}
    },
    mounted() {
      this.$store.commit('setTitle', 'recordRTC')

      videoElement = this.$el.querySelector('video')

      // if recording only audio, we should replace "HTMLVideoElement" with "HTMLAudioElement"
      if (isRecordOnlyAudio && currentBrowser == 'chromium') {
        var parentNode = videoElement.parentNode;
        parentNode.removeChild(videoElement);

        videoElement = document.createElement('audio');
        videoElement.style.padding = '.4em';
        videoElement.controls = true;
        parentNode.appendChild(videoElement);
      }

      new Promise(resolve => {
        if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {// chrome 56
          navigator.mediaDevices.enumerateDevices().then(resolve)
        } else {
          MediaStreamTrack.getSources(resolve)
        }
      }).then(devices => {
        var can_record_audio = false,
          can_record_video = false
        devices.forEach(item => {
          if (item.kind == 'audiooutput') {
          } else if (item.kind == 'audioinput') {
            can_record_audio = true
          } else if (item.kind == 'videoinput') {
            can_record_video = true
          } else {
            console.log(item)
          }
        })
        if (!can_record_audio) {
          console.log('没有录音设备')
          return
        }
        if (!can_record_video) {
          console.log('没有录像设备')
          return
        }

        navigator.getUserMedia({
          audio: true,
          video: true
        }, stream => {
          mediaStream = stream

          videoElement.src = window.URL.createObjectURL(stream)
          videoElement.play()

          audioRecorder = RecordRTC(stream, {
            type: isFirefox ? 'video' : 'audio',
            recorderType: isFirefox ? RecordRTC.MediaStreamRecorder : RecordRTC.StereoAudioRecorder // force WebAudio for all browsers even for Firefox/MS-Edge
          })
          videoRecorder = RecordRTC(stream, {
            type: videoFile.indexOf('gif') == -1 ? 'video' : 'gif',
            recorderType: isFirefox ? RecordRTC.MediaStreamRecorder : RecordRTC.WhammyRecorder
          })

          if (isFirefox) {
            audioRecorder.startRecording()
            return
          }
          videoRecorder.initRecorder(function () {
            audioRecorder.initRecorder(function () {
              videoRecorder.startRecording()
              audioRecorder.startRecording()
            })
          })

          setTimeout(() => {
            this.splitRecord()
          }, 2000)
        }, error => {
          alert(JSON.stringify(error))
        })
      })
    },
    methods: {
      postFiles(video) {
        // getting unique identifier for the file name
        if (window.crypto) {
          var a = window.crypto.getRandomValues(new Uint32Array(3))
          fileName = ''
          for (var i = 0, l = a.length; i < l; i++)
            fileName += a[i].toString(36)
        } else {
          fileName = (Math.random() * new Date().getTime()).toString(36).replace(/\./g, '')
        }
        var files = {
          audio: {
            name: fileName + '.' + audio.blob.type.split('/')[1], // MUST be wav or ogg
            type: audio.blob.type,
            contents: audio.dataURL
          }
        }
        if (video) {
          files.video = {
            name: fileName + '.' + video.blob.type.split('/')[1], // MUST be webm or mp4
            type: video.blob.type,
            contents: video.dataURL
          }
        }
        axios.post(global.server + '/uploadRecord.do', files).then(result => {
          const obj = result.data
          if (obj.result == 0) {
            this.splitRecord()
          } else if (obj.result == -1) {
            console.log(obj.msg)
          }
        }, result => {
          console.log(result)
        })
      },
      splitRecord() {
        audioRecorder.stopRecording(() => {
          if (isFirefox) {
            //this.convertStreams(audioRecorder.blob, audioRecorder.blob)
            audioRecorder.getDataURL(audioDataURL => {
              this.postFiles({
                blob: audioRecorder.getBlob(),
                dataURL: audioDataURL
              })
            })
            return
          }
          videoRecorder.stopRecording(() => {
            //this.convertStreams(videoRecorder.blob, audioRecorder.blob)
            audioRecorder.getDataURL(audioDataURL => {
              videoRecorder.getDataURL(videoDataURL => {
                this.postFiles({
                  blob: audioRecorder.getBlob(),
                  dataURL: audioDataURL
                }, {
                  blob: videoRecorder.getBlob(),
                  dataURL: videoDataURL
                })
              })
            })
          })
        })
      },
      convertStreams(videoBlob, audioBlob) {
        var vab;
        var aab;
        var buffersReady;
        var workerReady;
        var posted = false;
        var fileReader1 = new FileReader();
        fileReader1.onload = function () {
          vab = this.result;
          if (aab)
            buffersReady = true;
          if (buffersReady && workerReady && !posted)
            postMessage();
        };
        var fileReader2 = new FileReader();
        fileReader2.onload = function () {
          aab = this.result;
          if (vab)
            buffersReady = true;
          if (buffersReady && workerReady && !posted)
            postMessage();
        };
        fileReader1.readAsArrayBuffer(videoBlob);
        fileReader2.readAsArrayBuffer(audioBlob);
        if (!worker) {
          var blob = URL.createObjectURL(new Blob(['importScripts("' + workerPath + `");
		var now = Date.now;
		function print(text) {
		  postMessage({
		    type: "stdout",
			data: text
		  });
		};
		onmessage = function(event) {
		  var message = event.data;
		  if(message.type === "command") {
		    var Module = {
			  print: print,
			  printErr: print,
			  files: message.files || [],
			  arguments: message.arguments || [],
			  TOTAL_MEMORY: message.TOTAL_MEMORY || false
			};
			postMessage({
			  type: "start",
			  data: Module.arguments.join(" ")
			});
			postMessage({
			  type: "stdout",
			  data: "Received command: " + Module.arguments.join(" ") +((Module.TOTAL_MEMORY) ? ".  Processing with " + Module.TOTAL_MEMORY + " bits." : "")
			});
			var time = now();
			var result = ffmpeg_run(Module);
			var totalTime = now() - time;
			postMessage({
			  type: "stdout",
			  data: "Finished processing (took " + totalTime + "ms)"
			});
			postMessage({
			  type: "done",
			  data: result,
			  time: totalTime
			});
		  }
		};
		postMessage({
		  type: "ready"
		});`], {
            type: 'application/javascript'
          }))
          worker = new Worker(blob)
          URL.revokeObjectURL(blob)
        }
        worker.onmessage = (event) => {
          var message = event.data;
          if (message.type == "ready") {
            workerReady = true;
            if (buffersReady)
              postMessage();
          } else if (message.type == "stdout") {
          } else if (message.type == "start") {
          } else if (message.type == "done") {
            console.log(message.time)
            var result = message.data[0]
            var blob = new Blob([result.data], {
              type: 'video/mp4'
            })
            this.postBlob(blob)
          }
        }
        var postMessage = function () {
          posted = true;
          if (isFirefox) {
            worker.postMessage({
              type: 'command',
              arguments: [
                '-i', videoFile,
                '-c:v', 'mpeg4',
                '-c:a', 'vorbis',
                '-b:v', '6400k',
                '-b:a', '4800k',
                '-strict', 'experimental', 'output.mp4'
              ],
              files: [{
                data: new Uint8Array(vab),
                name: videoFile
              }]
            });
            return;
          }
          worker.postMessage({
            type: 'command',
            arguments: [
              '-i', videoFile,
              '-i', 'audio.wav',
              '-c:v', 'mpeg4',
              '-c:a', 'vorbis',
              '-b:v', '6400k',
              '-b:a', '4800k',
              '-strict', 'experimental', 'output.mp4'
            ],
            files: [{
              data: new Uint8Array(vab),
              name: videoFile
            }, {
              data: new Uint8Array(aab),
              name: "audio.wav"
            }]
          });
        };
      },
      postBlob(blob) {
        blobToUrl(blob, url => {
          axios.post(global.server + '/uploadRecord.do', {
            type: 'mp4',
            contents: url
          }).then(result => {
            const obj = result.data
            if (obj.result == 0) {
              this.splitRecord()
            } else if (obj.result == -1) {
              console.log(obj.msg)
            }
          }, result => {
            console.log(result)
          })
        })
      }
    }
  }
</script>
